package library

import (
	"crypto/hmac"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/jmoiron/sqlx"
	"golang.org/x/crypto/ripemd160"
	"log"
	"time"
	"vip_video/internal"
	"vip_video/models"
)

type TokenLibrary struct {
	Key    string
	UserId int64
	db     *sqlx.DB
}

func (tl *TokenLibrary) WithDB(db *sqlx.DB) *TokenLibrary {
	tl.db = db
	return tl
}

func NewTokenLibrary() *TokenLibrary {
	return &TokenLibrary{}
}

func (tl *TokenLibrary) WithKey(key string) *TokenLibrary {
	tl.Key = key
	return tl
}

func (tl *TokenLibrary) WithUserId(userId int64) *TokenLibrary {
	tl.UserId = userId
	return tl
}

func (tl *TokenLibrary) Set(token string) bool {
	log.Printf("新增token:%s", token)
	encryptToken := tl.HashHmacToken(token)
	log.Printf("加密后的token:%s", encryptToken)
	_, err := tl.db.NamedExec(
		"insert into fa_user_token(token,user_id,createtime,expiretime) values (:token,:user_id,:createtime,:expiretime)",
		map[string]any{
			"token":      encryptToken,
			"user_id":    tl.UserId,
			"createtime": time.Now().Unix(),
			"expiretime": internal.NowTimestamp() + 3600,
		},
	)
	if err != nil {
		return false
	}
	return true
}

// HashHmacToken 加密 token
func (tl *TokenLibrary) HashHmacToken(token string) string {
	h := hmac.New(ripemd160.New, []byte(tl.Key))
	h.Write([]byte(token))
	return hex.EncodeToString(h.Sum(nil))
}

func (tl *TokenLibrary) Get(token string) (int64, error) {
	log.Printf("获取token:%s", token)
	token = tl.HashHmacToken(token)
	log.Printf("加密后的token:%s", token)
	var userToken models.UserTokenModel
	err := tl.db.Get(
		&userToken,
		"select * from fa_user_token where token=? limit 1;",
		token,
	)
	if err != nil {
		log.Printf("查询数据库令牌失败:%s", err.Error())
		return 0, errors.New(fmt.Sprintf("查询令牌失败:%s", token))
	}
	if userToken.ExpireTime != nil && *userToken.ExpireTime <= internal.NowTimestamp() {
		//令牌已过期,删除 token
		_, _ = tl.db.NamedExec(
			"delete from fa_user_token where token=:token",
			map[string]any{
				"token": token,
			},
		)
		return 0, errors.New("未授权")
	}
	return userToken.UserId, nil
}
